// wnfs-share.cpp : Defines the entry point for the console application.
//

//#include "targetver.h"

extern "C"
{
#include "oncrpc-wrapper.h"
}

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <tchar.h>
#include <vector>
//#include <winsock2.h>

typedef std::vector<SOCKET> socket_vector_t;
typedef std::vector<char> buffer_t;

extern "C" {
int verbose = 1;
void reg_service(struct svc_req *, SVCXPRT *);
}

BOOL mountStart ();
BOOL nfsStart ();

///////////////////////////////////////////////////
// RPC

const short PMAP_PORT = 111;
///////////////////////////////////////////////////

void start()
{
  int res;
  int sock;
  struct sockaddr_in addr;
  SVCXPRT *xprt;
  const int len = sizeof(struct sockaddr_in);

  sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (INVALID_SOCKET == sock) 
  {
    char msg[]="cannot create socket";
    printf("%s\n",msg);
    return;
  }

  addr.sin_addr.s_addr = 0;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(PMAPPORT);
  res = bind(sock, (struct sockaddr *)&addr, len);
  if (0 != res) 
  {
    char msg[]="cannot bind";
    printf("%s\n",msg);
    return;
  }

  xprt = wnfs_svcudp_create(sock);
  if (nullptr == xprt) 
  {
    char msg[]="couldn't do udp_create";
    printf("%s\n",msg);
    return;
  }

  sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (0 > sock) 
  {
    char msg[]="cannot create socket";
    printf("%s\n",msg);
    return;
  }

  res = bind(sock, (struct sockaddr *)&addr, len);
  if (0 != res) 
  {
    char msg[]="cannot bind";
    printf("%s\n",msg);
    return;
  }

  xprt = wnfs_svctcp_create(sock, 0, 0);
  if (nullptr == xprt) 
  {
    char msg[]="couldn't do tcp_create";
    printf("%s\n",msg);
    return;
  }

  BOOL ret;
  ret = wnfs_svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
  assert(ret);

  DWORD TID;
  HANDLE threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)svc_run, NULL, 0, &TID);
  if (!threadHandle)
    goto exit_portmap;

  printf("%s\n", "Portmap service for Windows95 up and ready!");

  ret = mountStart();
  assert(ret);
  ret = nfsStart();
  assert(ret);

  DWORD dwWait = WaitForSingleObject(threadHandle, INFINITE);
  TerminateThread(threadHandle, 0);

exit_portmap:

  {
    char msg[]="Portmap service terminates!";
    printf("%s\n",msg);
  }

  return;
}

int init ()
{
  /*
  // ---------------
  {
    sMount = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    assert(sMount);

    sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_addr.S_un.S_addr = INADDR_ANY;
    sa.sin_port = htons(DaemonMountPort);

    res = bind(sMount, (sockaddr *)&sa, sizeof(sa));
    assert(0 == res);
    res = listen(sMount, 0);
    assert(0 == res);
  }
  // ---------------
  */
  return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
  int res;
  WSADATA wsaData = {0};

  res = WSAStartup(MAKEWORD(2, 2), &wsaData);
  assert(0 == res);
  if (res != 0) 
  {
    printf("WSAStartup() failed: %d\n", res);
    return 1;
  }

  // ---------------------
  res = init();
  assert(0 == res);

  res = rpc_nt_init();
  assert(0 == res);

  start();

  rpc_nt_exit();

  WSACleanup();

  return 0;
}

